package cn.xshi.oauth.util;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.message.AuthException;

import com.alibaba.fastjson.JSON;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import org.apache.commons.codec.binary.Base64;

/**
 * @Desc JWT
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
public class JwtUtil {

	/**
	 * token有效期 （30 min）
	 */
	private static final long JWT_VALIDITYTIME = 1800000;
	
	/**
	 * token签名
	 */
	private static final String JWT_SECRET = "JEHC_JWT_SECRET";
	
	private static final JwtUtil jwtUtil = new JwtUtil();
	
	public static JwtUtil jwtUtil() {
		return jwtUtil;
	}
	
	public JwtUtil() {}

    public Map verifyJwtToken(String token) throws AuthException {
        SecretKey secretKey = generalKey();
        try {
            Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
            String subject = claims.getSubject();
            if (subject == null || subject.trim().length() == 0) {
                return null;
            }
            return JSON.parseObject(subject, HashMap.class);
        } catch (SignatureException | MalformedJwtException e) {
            // jwt 签名错误或解析错误，可能是伪造的，不能相信
        	throw new AuthException("jwt token 签名错误或解析错误。");
        } catch (ExpiredJwtException e) {
            // jwt 已经过期
        	throw new AuthException("jwt token 已过期，请重新登录。");
        }
    }

    public String createJwtToken(Map map) {
        String subject = JSON.toJSONString(map);
        SecretKey secretKey = generalKey();

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder()
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm,secretKey);
        if (JWT_VALIDITYTIME > 0) {
            long expMillis = nowMillis + JWT_VALIDITYTIME;
            builder.setExpiration(new Date(expMillis));
        }
        return builder.compact();
    }
    
    /**
     * 通过未过期的token重新生成一个token
     * @param token  未过期token
     * @return 重新生成一个token
     * @throws AuthException 
     */
    public String refreshJwtToken(String token) throws AuthException{
    	Map subjectMap = verifyJwtToken(token);
    	String refreshToken = null;
    	if(subjectMap != null){
    		refreshToken = createJwtToken(subjectMap);
    	}
    	return refreshToken;
    }


    private SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

//    public static void main(String[] args) throws AuthException {
//    	Map<String, Object> map =  new HashMap<String, Object>();
//    	map.put("username", "MonitorMode");
//    	map.put("clientid", "3EB9B65D845F49E1AD311A26CE24ED2B");
//
//
//    	String token = JwtUtil.jwtUtil.createJwtToken(map);
//    	System.out.println("createtoken:" + token);
////    	Map<String, Object> sub = JwtUtil.jwtUtil.verifyJwtToken(token);
////    	System.out.println(sub);
//
//    	map =  new HashMap<String, Object>();
//    	map.put("username", "jEhcModule");
//    	map.put("clientid", "3EB9B65D845F49E1AD311A26CE24ED2B");
//
//    	token = JwtUtil.jwtUtil.createJwtToken(map);
//    	System.out.println("createtoken:" + token);
//
////    	//刷新Token
////    	String token1 = JwtUtil.jwtUtil().refreshJwtToken(token);
////    	System.out.println("reCreatetoken:" + token1);
////    	Map<String, Object> sub1 = JwtUtil.jwtUtil.verifyJwtToken(token1);
////    	System.out.println(sub1);
//	}
}
